#include "myapplication.h"
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// methodes d'initialisation a mettre dans init()
//
// methodes actualisees a chaque raffraichissement -> dans frameEnded()
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

using namespace Ogre;
using namespace std;

//************************************************************
// Implementation of MyApplication
//************************************************************
MyApplication::MyApplication() : OgreApplication("VISAGEFS"), mSelected(NULL), myVisualisation(NULL)
{
}

MyApplication::~MyApplication()
{
	delete myVisualisation;
}


//redefinition de la methode mouseReleased MouseListener
void MyApplication::mouseReleased(Ogre::MouseEvent* e)
{
    //clic gauche
    if (e->getButtonID() == InputEvent::BUTTON0_MASK) 
    { 
        //double clic gauche        
     if (mButtonTimer->getMilliseconds()<DOUBLECLICKDELAY)
     {
        mCamera->setPosition(mSelected->getParentNode()->getPosition() + Vector3(XCAMERASTART,YCAMERASTART,ZCAMERASTART));
        mCamera->lookAt(mSelected->getParentNode()->getPosition());
        //fic->setCaption("double clik"); 
     }
     //}
     else
     //clic normal
     {
            // Deselect old one if any
            if (mSelected) mSelected->getParentSceneNode()->showBoundingBox(false);            // Use a ray scene query to find where we clicked
            Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(),e->getY());
            mRaySceneQuery->setRay(mouseRay);
            mRaySceneQuery->setSortByDistance(true);
            RaySceneQueryResult &result = mRaySceneQuery->execute();//TESTING1
            RaySceneQueryResult::iterator itr;
            // loop through the results
                      for ( itr = result.begin( ); itr != result.end(); itr++ )
            {
                    //on selectionne le premier objet de type entity
                    if (itr->movable->getMovableType() == "Entity" && itr->movable->getName() != "Ground" )
                    {
                        mSelected = (Entity*)(itr->movable);
                        mSelected->getParentSceneNode()->showBoundingBox(true);
                        fileOverlay->setCaption(itr->movable->getName());
                        break;
                    }
            }
            //reset du timer
            mButtonTimer->reset();
        }
    }
}

void MyApplication::configOverlay()
{
	//configuration des panneaux d'affichage
	mDebugPanelOverlay = OverlayManager::getSingleton().getByName("PanelOverlay");
    mDebugPanelOverlay->show();
	//configuration des différents elements du panneau 
	fileOverlay = OverlayManager::getSingleton().getOverlayElement("Fichier");
    debugOverlay = OverlayManager::getSingleton().getOverlayElement("Debug");
}

//fonction d'initialisation de l'application
void MyApplication::init()
{
	//configuration du panneau d'affichage et de ses elements
	configOverlay();


    //Affichage d'un message de test
    myVisualisation->afficherMessage("Debug_test");

    //creation d'un timer pour gerer le double click de la souris
    mButtonTimer =  PlatformManager::getSingleton().createTimer();    mButtonTimer->reset();

    /*SceneNode * rootScene = mSceneManager->getRootSceneNode();*/
    nbLignes = 0;

    ligneMaterial = MaterialManager::getSingleton().create("ligneMaterial","debugger");
    ligneMaterial->setReceiveShadows(false);
    ligneMaterial->getTechnique(0)->setLightingEnabled(true);
    ligneMaterial->getTechnique(0)->getPass(0)->setDiffuse(0,0,1,0);
    ligneMaterial->getTechnique(0)->getPass(0)->setAmbient(0,0,1);
    ligneMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,1);


    mSceneManager->setAmbientLight(ColourValue(0.7f,0.7f,1.0f));

    //Configuration de la camera
    mCamera->setPosition(Vector3(XCAMERASTART,YCAMERASTART,ZCAMERASTART));
    mCamera->lookAt(Vector3(XCAMERASTART,YCAMERASTART,ZCAMERASTART-500));

    //Ajout de cubes
    Entity *cube1 = mSceneManager->createEntity("Racine","CubeRed.mesh");
    SceneNode* cube1Node = mSceneManager->getRootSceneNode()->createChildSceneNode("cube1Node");
    cube1Node->scale(Vector3(SCALE,SCALE,SCALE));
    cube1Node->attachObject(cube1);

    mSelected = mSceneManager->getEntity("Racine");

    //on recupere le rayon du premier cube
    Real r = mSceneManager->getEntity("Racine")->getBoundingRadius();

	Entity *cube2 = mSceneManager->createEntity("Rep2","CubeOrange.mesh");
    SceneNode* cube2Node = cube1Node->createChildSceneNode("cube2Node",(Vector3(-1,1,0)*FACTOR));
    cube2Node->attachObject(cube2);

	myVisualisation->ligne(cube1Node,cube1Node->getPosition(),cube2Node->getPosition());

    // Adds a ground
    MeshManager::getSingleton().createPlane("plane.mesh","Custom",Plane(Vector3::UNIT_Z,Vector3(0.0,0.0,-r)),500*r,500*r,20,20);
    Entity* ground = mSceneManager->createEntity("Ground","plane.mesh");
    ground->setMaterialName("Examples/Rocky");
    SceneNode* groundNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
    groundNode->attachObject(ground);
    groundNode->setOrientation(Quaternion(Radian(-Math::HALF_PI),Vector3::UNIT_X));

    // Activate shadows
    /*mSceneManager->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_MODULATIVE);
    mSceneManager->setShadowColour(Ogre::ColourValue(0.5f,0.5f,0.5f));
    cube1->setCastShadows(true);
    cube2->setCastShadows(true);
    cube3->setCastShadows(true);
    cube4->setCastShadows(true);*/

    mSceneManager->setSkyBox(true,"Examples/StormySkyBox",50);
    mRaySceneQuery = mSceneManager->createRayQuery(Ray());

//DEBUG
    mEventProcessor->addMouseListener(this);

}

//redéfinition de la méthode de ogreapplication
bool MyApplication::frameStarted(const FrameEvent& evt)
{
    return OgreApplication::frameStarted(evt);
}

//redéfinition de la méthode de ogreapplication
bool MyApplication::frameEnded(const FrameEvent& evt)
{
  //déplacement avec les flêches du clavier en fin de frame
  mCamera->moveRelative(move);
  //rotation de l'objet selectionné en fin de frame
  mSelected->getParentNode()->yaw(Degree(moveRootNode));
  return !mQuitRequested;
}

//redéfinition de la méthode de ogreapplication
void MyApplication::keyPressed(KeyEvent *e)
{
    if (e->getKey() == KC_LEFT)
    {
        move = Vector3(-5.0,0.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_RIGHT)
    {
        move = Vector3(5.0,0.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_UP)
    {
        move = Vector3(0.0,5.0,0.0);
        e->consume();
    }
    else if (e->getKey() == KC_DOWN)
    {
        move = Vector3(0.0,-5.0,0.0);
        e->consume();
    }
    //zoom in
    else if (e->getKey() == KC_I)
    {
        move = Vector3(0.0,0.0,-5.0);
        e->consume();
    }
    //zoom out 
    else if (e->getKey() == KC_O)
    {
        move = Vector3(0.0,0.0,5.0);
        e->consume();
    }
    else if (e->getKey() == KC_O)
    {
        move = Vector3(0.0,0.0,5.0);
        e->consume();
    } 
    else if (e->getKey() == KC_Q)
    {
        moveRootNode=-2;
        e->consume();
    }
    else if (e->getKey() == KC_D)
    {
        //mCamera->yaw(Degree(1));
        moveRootNode=2;
        //mSceneManager->getRootSceneNode()->yaw(Degree(10));
        e->consume();
    }
    else if (e->getKey() == KC_SPACE)
    {
        mCamera->setPosition(Vector3(XCAMERASTART,YCAMERASTART,ZCAMERASTART));
        mCamera->lookAt(Vector3(XCAMERASTART,YCAMERASTART,ZCAMERASTART-500));
        e->consume();
    }
    /* pour pouvoir prendre une screenshot, plus tard     
    else if (e->getKey() == KC_SYSRQ)
    {
        RenderWindow::writeContentsToFile("screenshot.png");
        e->consume();
    }*/

}

//redéfinition de la méthode de ogreapplication
void MyApplication::keyClicked(KeyEvent *e)
{
    if (e->getKey() == KC_ESCAPE)
    {
        requestQuit();
        e->consume();
    }
}

//redéfinition de la méthode de ogreapplication
void MyApplication::keyReleased(KeyEvent *e)
{
    move = Vector3(0,0,0);
    moveRootNode = 0;
    e->consume();
}

//setters
void MyApplication::setVisualisation(Visualisation * v)
{
	myVisualisation = new Visualisation;
	myVisualisation = v;
}
